package com.liyj.heroadmin.controller;

import com.liyj.heroadmin.config.ESClient;
import com.liyj.heroadmin.vo.SearchBody;
import org.elasticsearch.action.admin.indices.alias.Alias;

import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;

import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/search")
public class SearchController {

    @Autowired
    RestHighLevelClient elasticsearchClient;

    @GetMapping("/")
    public String hello() {

        return "Hello ElasticSearch";
    }


    //创建索引
    @GetMapping("/createIndex")
    public Boolean createIndex() throws IOException {

        CreateIndexRequest request = new CreateIndexRequest("result_data_01");
        request.settings(Settings.builder()
                .put("index.number_of_shards", 1)
                .put("index.number_of_replicas", 0)
        );
        Map<String, Object> properties = new HashMap<>();

        Map<String, Object> title = new HashMap<>();
        title.put("type", "text");
        title.put("analyzer", "ik_max_word");
        title.put("search_analyzer", "ik_max_word");
        properties.put("title", title);

        Map<String, Object> type = new HashMap<>();
        type.put("type", "keyword");
        properties.put("type", type);

        Map<String, Object> secretClass = new HashMap<>();
        secretClass.put("type", "keyword");
        properties.put("secretClass", secretClass);

        Map<String, Object> number = new HashMap<>();
        number.put("type", "keyword");
        number.put("index", false);
        properties.put("number", secretClass);

        Map<String, Object> company = new HashMap<>();
        company.put("type", "text");
        company.put("analyzer", "ik_max_word");
        company.put("search_analyzer", "ik_max_word");
        properties.put("company", company);

        Map<String, Object> author = new HashMap<>();
        author.put("type", "keyword");
        properties.put("author", author);

        Map<String, Object> KeyWord = new HashMap<>();
        KeyWord.put("type", "text");
        KeyWord.put("analyzer", "ik_max_word");
        KeyWord.put("search_analyzer", "ik_max_word");
        properties.put("KeyWord", KeyWord);

        Map<String, Object> pageCount = new HashMap<>();
        pageCount.put("type", "keyword");
        pageCount.put("index", false);
        properties.put("pageCount", pageCount);

        Map<String, Object> ratifier = new HashMap<>();
        ratifier.put("type", "keyword");
        ratifier.put("index", false);
        properties.put("ratifier", ratifier);

        Map<String, Object> field = new HashMap<>();
        field.put("type", "keyword");
        properties.put("field", author);


        Map<String, Object> abstracts = new HashMap<>();
        abstracts.put("type", "text");
        abstracts.put("analyzer", "ik_max_word");
        abstracts.put("search_analyzer", "ik_max_word");
        properties.put("abstracts", abstracts);

        Map<String, Object> subtitle1 = new HashMap<>();
        subtitle1.put("type", "text");
        subtitle1.put("analyzer", "ik_max_word");
        subtitle1.put("search_analyzer", "ik_max_word");
        properties.put("subtitle1", subtitle1);

        Map<String, Object> subContent1 = new HashMap<>();
        subContent1.put("type", "text");
        subContent1.put("analyzer", "ik_max_word");
        subContent1.put("search_analyzer", "ik_max_word");
        properties.put("subContent1", subContent1);


        Map<String, Object> subtitle2 = new HashMap<>();
        subtitle2.put("type", "text");
        subtitle2.put("analyzer", "ik_max_word");
        subtitle2.put("search_analyzer", "ik_max_word");
        properties.put("subtitle2", subtitle2);

        Map<String, Object> subContent2 = new HashMap<>();
        subContent2.put("type", "text");
        subContent2.put("analyzer", "ik_max_word");
        subContent2.put("search_analyzer", "ik_max_word");
        properties.put("subContent2", subContent2);

        Map<String, Object> mapping = new HashMap<>();
        mapping.put("properties", properties);
        request.mapping("_doc",mapping);


        request.alias(new Alias("result_data"));

        CreateIndexResponse re = elasticsearchClient.indices().create(request, RequestOptions.DEFAULT);
        return re.isAcknowledged();
    }


    //信息检索
    @ResponseBody
    @PostMapping("match")
    public  Map<String,Object> main(@RequestBody SearchBody searchbody) throws IOException {


        System.out.println(searchbody.toString());
        Integer start = searchbody.getStart();
        Integer size = searchbody.getSize();
        String keyword = searchbody.getKeyword();




        if (start == null || size ==null) {
            start = 0;
            size = 10;
        }



        Map<String,Object> datas = new HashMap<>();
        List<Map<String,Object>> phits = new ArrayList<>();


        SearchRequest searchRequest = new SearchRequest("result_data");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//        searchSourceBuilder.fetchSource(new String[]{"title","type","company","KeyWord","subtitle1","subtitle2","subContent1","subContent2"},new String[]{});

        searchSourceBuilder.query(QueryBuilders.multiMatchQuery(keyword,"title","company","KeyWord","subtitle1","subtitle2","subContent1","subContent2"));
        searchSourceBuilder.highlighter(new HighlightBuilder().requireFieldMatch(false).field("title").field("company").field("KeyWord").field("subtitle1").numOfFragments(1).fragmentSize(500).noMatchSize(0));



        searchSourceBuilder.from(start);
        searchSourceBuilder.size(size);
        searchRequest.source(searchSourceBuilder);
        System.out.println( searchRequest.toString());

        SearchResponse searchResponse = elasticsearchClient.search(searchRequest, RequestOptions.DEFAULT);


        SearchHits hits = searchResponse.getHits();
        System.out.println(hits.getHits());
        for (SearchHit hit : hits.getHits()) {
            Map<String,Object> phit = new HashMap<>();
            phit.put("id",hit.getId());

            phit.put("title",hit.getSourceAsMap().get("title") == null ? "":hit.getSourceAsMap().get("title").toString() );
            phit.put("type",hit.getSourceAsMap().get("type") == null ? "":hit.getSourceAsMap().get("type").toString());
            phit.put("company",hit.getSourceAsMap().get("company") == null ? "":hit.getSourceAsMap().get("company").toString());
            phit.put("KeyWord",hit.getSourceAsMap().get("KeyWord") == null ? "":hit.getSourceAsMap().get("KeyWord").toString());
            phit.put("subtitle1",hit.getSourceAsMap().get("subtitle1") == null ? "":hit.getSourceAsMap().get("subtitle1").toString());
            phit.put("subContent1",hit.getSourceAsMap().get("subContent1") == null ? "":hit.getSourceAsMap().get("subContent1").toString());
            phit.put("subtitle2",hit.getSourceAsMap().get("subtitle2") == null ? "":hit.getSourceAsMap().get("subtitle2").toString());
            phit.put("subContent2",hit.getSourceAsMap().get("subContent2") == null ? "":hit.getSourceAsMap().get("subContent2").toString());

            phit.put("abstracts",hit.getSourceAsMap().get("abstracts") == null ? "":hit.getSourceAsMap().get("abstracts").toString());
            //phit.put("subContent1",hit.getSourceAsMap().get("subContent1").toString());
           // phit.put("subtitle2",hit.getSourceAsMap().get("subtitle2").toString());
            //phit.put("subContent2",hit.getSourceAsMap().get("subContent2").toString());
            phits.add(phit);
        }

        long totalHits = hits.getTotalHits();
        // the total number of hits, must be interpreted in the context of totalHits.relation
        long numHits = totalHits;
        // whether the number of hits is accurate (EQUAL_TO) or a lower bound of the total (GREATER_THAN_OR_EQUAL_TO)
//        TotalHits.Relation relation = totalHits.relation;
        int hsize = hits.getHits().length;

        datas.put("total",numHits);
        datas.put("start",start);
        datas.put("end",start+hsize);
        if(hsize <= size) {
            datas.put("length", hsize);
        } else {
            datas.put("length", size);
        }
        datas.put("pages",(int)Math.ceil((double)numHits/(double)size));
        datas.put("data",phits);
        return datas;

    }


}
